<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>03_计算属性和监视</title>
  </head>
  <body>
    <!--
      1. 计算属性
        在computed属性对象中定义计算属性的方法
        在页面中使用{{方法名}}来显示计算的结果
      2. 监视属性:
        通过通过vm对象的$watch()或watch配置来监视指定的属性
        当属性变化时, 回调函数自动调用, 在函数内部进行计算
      3. 计算属性高级:
        通过getter/setter实现对属性数据的显示和监视
        计算属性存在缓存, 多次读取只执行一次getter计算
    -->
    <div id="app">
      <!-- 姓:
      <input type="text" placeholder="First Name" :value="firstName" /><br />
      名: <input type="text" placeholder="Last Name" :value="lastName" /><br /> -->

      姓:
      <input type="text" placeholder="First Name" v-model="firstName" /><br />
      名: <input type="text" placeholder="Last Name" v-model="lastName" /><br />
      姓名1:
      <input type="text" placeholder="Full Name1" :value="fullName1" /><br />
      姓名2:
      <input type="text" placeholder="Full Name2" v-model="fullName2" /><br />

      <p>{{ count }}</p>
      <button @click="update">按钮</button>

      <p>{{ person.age }}</p>
      <button @click="updatePerson">更新person</button>
    </div>

    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript">
      /*
        1. 计算属性
          根据一个或多个值参与计算，生成新的结果
          一定有返回值，返回值就是计算属性要显示的内容
          不能做异步操作
          有缓存，只有依赖的值发生变化才会重新计算
        2. 监视属性
          监视一个已存在的属性，一旦属性发生变化，就会触发回调
          没有返回值
          可以进行异步操作
      */

      new Vue({
        el: "#app",
        // 数据代理：将data、computed、methods数据挂载到this上，用户可以直接通过this访问数据
        // 简单方便
        data: {
          firstName: "李",
          lastName: "沛华",
          count: 0,
          person: {
            age: 20,
          },
        },
        computed: {
          // 计算属性
          // 有两种写法：1. 只读的计算属性 2. 可读可写的计算属性
          // 1. 只读的计算属性
          // 当你要读取fullName1的值时，调用fullName1函数，得到函数返回值，函数返回值
          // 就是计算属性fullName1的值
          fullName1() {
            // 返回值就是fullName1的值
            // 特点: 一旦里面依赖的数据发生变化，就会重新计算
            // 特点: 有缓存
            // console.log(this);
            return this.firstName + " " + this.lastName;
          },
          // 2. 可读可写的计算属性
          fullName2: {
            get() {
              // 当你读取fullName2的值，会调用get方法，get方法的返回值就是fullName2的值
              return this.firstName + " " + this.lastName;
            },
            set(val) {
              // 当你设置fullName2的值，会调用set方法，set方法的决定如何更新
              // val就是更新的值
              const [firstName, lastName] = val.split(" ");
              this.firstName = firstName;
              this.lastName = lastName;
            },
          },
        },
        methods: {
          update() {
            console.log(this);
            this.count++;
          },
          updatePerson() {
            this.person.age++;
            // this.person = { age: 111 };
          },
        },
        watch: {
          // 定义属性，监视属性
          // 作用：监视已存在的属性，一旦这个属性发生变化，就会触发函数
          // firstName(newVal, oldVal) {
          //   console.log(newVal, oldVal);
          // },

          firstName: {
            handler(newVal, oldVal) {
              console.log(newVal, oldVal);
            },
            immediate: true, // 一上来就触发
          },

          // 监视属性只能监视，属性的值的变化
          person: {
            handler(newVal, oldVal) {
              console.log(newVal, oldVal);
            },
            deep: true, // 深度监视（对象属性的变化）
          },
        },
      });
    </script>
  </body>
</html>
